#!/usr/bin/env python3

import re
import json
import os
import sys


project_path = "../../"
flatdump_path = project_path+"build/coderef/examples-256/flatdump/"
output_file_path = project_path + 'code/xrnlib/lib/xrn_interfaces/c/inc/xrn_lib_interposer.h'
output_file_path1 = project_path + 'code/xrnlib/app/parser/inc/xrn_lib_interposer_dll.h' 
if ( len(sys.argv) == 4 ) :
    output_file_path = sys.argv[1]
    output_file_path1 = sys.argv[2]
    flatdump_path = sys.argv[3]

defines_to_look_for = ['XRN_SUBJECT_CERTIFICATE_LENGTH','XRN_BUFF_SIZE','XBIT_TYPE','XRN_ENC_PASS_BUFF_SIZE','XRN_BUFFER_ENC_CHECK_SIZE','XRN_BUFFER_ENC_BIST_SIZE','XSUCCESS','XRN_MAX_MERGE_PARALLELISM']
structs_to_look_for = ['xrn_log_t','xrn_crypto_lib_header_t','xrn_encoding_checks_t','xrn_encoding_param_t','xrn_encoding_tmp_param_t','xrn_encoding_settings_t','xrn_interface_settings_t','xrn_crypto_extra_settings_t','xblock_settings_t']
enums_to_look_for = ['xrn_encoding_mode_t','xrn_check_initialization_mode_t','xrn_lib_xtype_t']

# Read the input .h file

with open(project_path +'scripts/backend/' + 'filelist.json', 'r') as file:
    jsondata = file.read()
filelists_json = json.loads( jsondata )

# fetch library header files which are not backend
input_file_paths = []
for file in filelists_json["libh"]:
    if not ( "_backend" in file ) :
        input_file_paths.append( flatdump_path + os.path.basename(file) ) 


parser_file = ""
for file in filelists_json["parserc"]:
    if ( "parser.c" in file ) :
        parser_file = project_path + file


def find_words_ending_with_dll(input_file):
  """Finds all words in the given input file that end with "_wrapper".

  Args:
    input_file: A string containing the path to the input file.

  Returns:
    A list of all words in the input file that end with "_wrapper".
  """

  words_ending_with_wrapper = []
  with open(input_file, 'r') as f:
    for line in f:
      words = re.findall(r'\w+', line)
      words_ending_with_wrapper.extend([word for word in words if word.endswith('_dll')])
  return words_ending_with_wrapper




input_file = parser_file

words_ending_with_dll = find_words_ending_with_dll(input_file)
words_processed = []


# Define a regular expression pattern to match function declarations with multiline definitions
function_pattern  = r'(\w+\s*\**\s*)\s+(\w+)\s*\(([^)]*)\)\s*;'


function_info_pattern = r'(\w+(\s*\*\s*)*)\s*(\w+(\[\w+\])*)'

# Define a regular expression pattern to extract enumeration,struct,define
enum_pattern = r'\s*enum\s*{([^}]*)}\s*(\w+)'

struct_pattern = r'\s*struct\s+(\w+)\s*{([^}]*\s*(\w+))'

define_pattern = r'#define\s+(\w+)\s+(.+)'

with open(output_file_path,"w") as output_file:

    output_file.write('#ifndef XRN_TYPEDEF_H \n#define XRN_TYPEDEF_H\n#include <stdio.h>\n#include <stdint.h>\n#include <stdbool.h>\n\n')

    for de in defines_to_look_for:

        for input_file_path in input_file_paths:

            with open(input_file_path, 'r') as file:
                content = file.read()                
            
            defines = re.findall(define_pattern,content)
            for define in defines:
                if de == define[0]:
                    output_file.write('#define '+define[0]+" "+define[1]+"\n")
        output_file.write("\n")
    for en in enums_to_look_for:
        for input_file_path in input_file_paths:

            with open(input_file_path, 'r') as file:
                content = file.read()                
            
            enumerations = re.findall(enum_pattern,content)
            for enumeration in enumerations:
                
                    if enumeration[1] == en:
                        output_file.write("typedef enum {")
                        first = 0
                        e_con = enumeration[0].split(',')
                        for con in e_con:
                            
                            if first == 0:
                                first = 1
                            else:
                                output_file.write(",")
                            output_file.write(con)
                        output_file.write('} '+enumeration[1]+";\n\n")        

    for st in structs_to_look_for:
        for input_file_path in input_file_paths:

            with open(input_file_path, 'r') as file:
                content = file.read()                
            
            structs = re.findall(struct_pattern,content)
            for struct in structs:
                
                    if struct[0] == st:
                        output_file.write("typedef struct "+ st + " {")
                        first = 0
                        s_con = struct[0].split(',')
                        output_file.write(struct[1])
                        output_file.write(';\n} '+struct[0]+";\n\n") 
    output_file.write('#endif\n')

with open(output_file_path1,"w") as output_file:
    output_file.write('#ifndef XRN_DLL_TYPEDEF_H \n#define XRN_DLL_TYPEDEF_H\n#include <stdio.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include "xrn_lib_interposer.h"\n\n')
    for input_file_path in input_file_paths:

        with open(input_file_path, 'r') as file:
            content = file.read()

        content = content.replace('\n', ' ')
        # Find all function declarations with multiline definitions in the content
        function_declarations = re.findall(function_pattern, content)

        # Process each function declaration
        for declaration in function_declarations:
            # Extract function name, return type, and arguments
            d_list = (declaration[2]).split(',')
            first = 0
            typ = declaration [0]
            dec = declaration [1] #[:-3]
            for word in words_ending_with_dll:
                word_ep = word[:-4]
                if word_ep == dec:
                    output_file.write( typ+ " (* " + dec +"_dll)( " )
                    words_ending_with_dll.remove(word)
                    words_processed.append(word)
                    for d in d_list: 
                        d = d.strip()
                        match = re.match(function_info_pattern, d)
                        if (match != None):
                            a ,b,c,d  =match.groups()
                            if first == 0:
                                first = 1
                            else:
                                output_file.write(",")
                            output_file.write (a + " ")
                            if d != None : 
                                output_file.write("* ")
                    output_file.write(");\n")
                    break

    output_file.write('\n#endif\n')
        






    # mixed_array = words_ending_with_dll + words_processed

    # seen = set()
    # unique_array = []
    # for element in words_ending_with_dll:
    #     if element not in seen:
    #         seen.add(element)
    #         unique_array.append(element)


    # for w in words_processed:
    #     if w in words_ending_with_dll:
    #         unique_array.remove(w)



    # print(sorted(unique_array))
